<?php

namespace common\app;

use cm;
use yii;
use ReflectionClass;
use ReflectionMethod;

class ReflectionAuth
{
    function getAllDocs($config, $sysAlias = '')
    {
        $data = [];
        foreach ($config as $conf) {
            if (empty($sysAlias) || $sysAlias == $conf['app']) {
                $docPath = PATH_ROOT . $conf['path'];
                $dirs = scandir($docPath);
                $appAuths['app'] = $conf['app'];
                $appAuths['auths'] = [];
                foreach ($dirs as $file) {
                    if ($file != '.' && $file != '..') {
                        $appAuths['auths'][] = $this->getFileAuths($docPath, $file, $conf['namespace']);
                    }
                }
                $data[] = $appAuths;
            }
        }
        return $data;
    }

    function checkCommon()
    {
        //-1：模块停用；-2：操作停用；-3：角色权限验证；0：未登录；1：通用权限通过；2：角色权限通过;3:没有权限限制
        $res = ["code" => 0, "msg" => ''];

        $namespace = str_replace("controller", 'interface', strtolower(Yii::$app->controller->className()));

        $action = strtolower(Yii::$app->controller->action->id);

        $reflection = new ReflectionClass ($namespace);
        $classDoc = $reflection->getDocComment();

        $deprecated = $this->getStrBoolByReg($classDoc, 'deprecated');
        if ($deprecated) {
            $res['code'] = -1;
            $res['msg'] = '模块已停用';
            return $res;
        }

        $methods = $this->parseMethod($reflection);//echo json_encode($methods);exit;
        foreach ($methods as $a) {
            if ($a['alias'] == $action) {
                if ($a['deprecated']) {
                    $res['code'] = -2;
                    $res['msg'] = '操作已停用';
                    return $res;
                }
                if ($a['guest']) {
                    $res['code'] = 3;
                    return $res;
                }
                if (Cm::$app->user->isGuest()) {
                    $res['code'] = 0;
                    $res['msg'] = '未登录';
                    return $res;
                }

                if ($a['common'] == 'get' && Yii::$app->request->method == 'GET') {
                    $res['code'] = 1;
                    return $res;
                }

                if ($a['common'] == 'post' && Yii::$app->request->method == 'POST') {
                    $res['code'] = 1;
                    return $res;
                }

                if ($a['common'] == "all") {
                    $res['code'] = 1;
                    return $res;
                }
                //echo json_encode($a);exit;
                foreach ($a['post'] as $p)
                {
                    if($p['common'])
                    {
                        $v=isset($_GET[$p['key']])?$_GET[$p['key']]:'';
                        if($v==$p['value'])
                        {
                            $res['code']=1;
                            return $res;
                        }
                    }
                }

                $res['code'] = -3;
                return $res;

            }
        }

        $res['code'] = 3;
        return $res;
    }

    private function getFileAuths($dirPath, $fileName, $namespace)
    {
        $filePath = $dirPath . '/' . $fileName;
        include_once $filePath;
        $className = rtrim($fileName, '.php');
        $namespace = $namespace . "\\{$className}";
        try {
            $reflection = new ReflectionClass ($namespace);
        } catch (\ReflectionException $e) {
        }
        $classDoc = $reflection->getDocComment();

        $data['alias'] = str_replace('interface', '', strtolower($className));
        $data['md5'] = md5($classDoc);
        $data['namespace'] = $namespace;
        $data['name'] = $this->getStrByReg($classDoc, 'name');
        $data['sort'] = $this->getStrByReg($classDoc, 'sort', 0);
        $data['remark'] = $this->getStrByReg($classDoc, 'remark');
        $data['deprecated'] = $this->getStrBoolByReg($classDoc, 'deprecated');
        $data['methods'] = $this->parseMethod($reflection);

        return $data;
    }

    private function getRoleInfo($sysAlias, $accountID)
    {

    }

    private function parseMethod($reflection)
    {
        $methodsArr = array();
        $methods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC);
        foreach ($methods as $method) {
            $doc = $method->getDocComment();

            $mArr = array();
            $mArr['name'] = $this->getStrByReg($doc, "name");
            $mArr['alias'] = str_replace('action', '', strtolower($method->name));
            $mArr['md5'] = md5($doc);
            $mArr['remark'] = $this->getStrByReg($doc, "remark");//描述

            $pageType = $this->getStrByReg($doc, 'type');//页面类型
            $mArr['type'] = empty($pageType) ? "page" : $pageType;
            $mArr['guest'] = $this->getStrBoolByReg($doc, 'guest');//是否不登录也可以访问 游客访问

            $mArr['deprecated'] = $this->getStrBoolByReg($doc, 'deprecated');//是否弃用

            $common = $this->getStrBoolByReg($doc, 'common');//是否通用，不需要权限验证
            $strCommon = $this->getStrByReg($doc, 'common');
            $common = !$common ? 'no' : (empty($strCommon) ? 'all' : $strCommon);
            $mArr['common'] = $common;

            $mArr['sort'] = $this->getStrByReg($doc, 'sort', 0);

            $mArr['case'] = $this->getStrByReg($doc, 'case', '[]');
            $mArr['post-remark'] = $this->getPostRemark($doc, 'post-remark');

            $mArr['get'] = $this->getStrsByReg($doc, 'get');
            $mArr['post'] = $this->getStrsByReg($doc, 'post');
            $mArr['getall'] = $this->getStrBoolByReg($doc, 'getall');
            $mArr['postall'] = $this->getStrBoolByReg($doc, 'postall');
            if ($common == 'get' && count($mArr['post']) > 1)
                $mArr['postall'] = true;
            if ($common == 'post' && count($mArr['get']) > 1)
                $mArr['getall'] = true;
            if ($common == "no") {
                if (count($mArr['post']) > 1)
                    $mArr['postall'] = true;
                if (count($mArr['get']) > 1)
                    $mArr['getall'] = true;
            }


            $methodsArr[] = $mArr;
        }
        return $methodsArr;
    }

    public function getStrByReg($doc, $reg, $str = '')
    {
        preg_match("/\@{$reg} .+/", $doc, $strArr);
        if (count($strArr) > 0) {
            $str = ltrim($strArr[0], "\@{$reg} ");
        }
        return $str;
    }

    public function getStrsByReg($doc, $reg)
    {
        $pArr = array();
        preg_match_all("/\@{$reg} .+/", $doc, $strArr);
        if (count($strArr) > 0) {
            foreach ($strArr[0] as $item) {
                $str = ltrim($item, "\@{$reg}");
                $str = trim($str);

                $pm = array('title' => '', "key" => "", "value" => "");
                $arr = explode(',', $str);
                foreach ($arr as $n) {
                    list($k, $v) = explode(':', $n);
                    if ($k == 't')
                        $pm['title'] = $v;
                    if ($k == 'k')
                        $pm['key'] = $v;
                    if ($k == 'v')
                        $pm['value'] = str_replace('，', ',', $v);

                    $pm['notnull'] = false;
                    if ($k == 'n')
                        $pm['notnull'] = true;

                    $pm['common'] = false;
                    if ($k == 'c')
                        $pm['common'] = true;
                }
                $pArr[] = $pm;
            }
        }
        return $pArr;
    }

    private function getPostRemark($doc, $reg)
    {
        $pArr = [];
        preg_match_all("/\@{$reg}.+/", $doc, $strArr);

        if (count($strArr) > 0) {
            foreach ($strArr[0] as $item) {

                preg_match("/\@{$reg}\-[a-z0-9\_\-]{1,}/", $item, $keys);

                if (count($keys) > 0) {

                    $keys = ltrim($keys[0], "\@{$reg}");
                    $keys = trim($keys);

                    $str = ltrim($item, "\@{$reg}-{$keys}");
                    $str = trim($str);

                    $type = 'string';
                    if (json_decode($str, true))
                        $type = 'json';

                    $pArr[$keys] = ['type'=>$type,'data'=>$str];
                }


            }
        }
        return $pArr;
    }

    private function getStrBoolByReg($doc, $reg)
    {
        $bool = false;
        preg_match("/\@{$reg}/", $doc, $strArr);
        if (count($strArr) > 0) {
            $bool = true;
        }
        return $bool;
    }
}

